/*
 * @Author: WuFeng <763467339@qq.com>
 * @Date: 2022-10-10 10:31:51
 * @LastEditTime: 2025-10-16 16:13:06
 * @LastEditors: WuFeng <763467339@qq.com>
 * @Description: 
 * @FilePath: \vue-code-design\api\codeDesign.js
 * @Copyright 版权声明
 */
// lodash
const _ = require('lodash')

// 代码生成service
const { genderCode } = require('../service/genderCode.js')

// 工具类
const {
  responseData
} = require('../utils/index')

//全局Express框架
const express = require("express")
const router = express.Router()
module.exports = router

//加载配置文件
const { config : dbConfig } = require("../config/mysql")
const mysql = require("mysql2")

// 创建数据库连接池
const pool = mysql.createPool(dbConfig)

// 创建Promise包装的查询函数
const query = (sql, params = []) => {
  return new Promise((resolve, reject) => {
    pool.getConnection((err, connection) => {
      if (err) {
        console.error('获取数据库连接失败:', err)
        return reject(err)
      }
      connection.query(sql, params, (err, results) => {
        connection.release() // 释放连接回池中
        if (err) {
          return reject(err)
        }
        resolve(results)
      })
    })
  })
}

// // 创建Promise包装的查询函数，带重试机制
// const query = async (sql, params = [], retryCount = 3) => {
//   try {
//     return new Promise((resolve, reject) => {
//       pool.getConnection((err, connection) => {
//         if (err) {
//           console.error('获取数据库连接失败:', err)
//           return reject(err)
//         }
        
//         // 检查连接是否健康
//         connection.ping((pingErr) => {
//           if (pingErr) {
//             connection.destroy() // 销毁不健康的连接
//             return reject(pingErr)
//           }
          
//           // 执行查询
//           connection.query(sql, params, (err, results) => {
//             connection.release() // 释放连接回池中
//             if (err) {
//               return reject(err)
//             }
//             resolve(results)
//           })
//         })
//       })
//     })
//   } catch (error) {
//     // 处理连接断开错误，进行重试
//     if ((error.code === 'PROTOCOL_CONNECTION_LOST' || error.code === 'ECONNRESET') && retryCount > 0) {
//       console.log(`数据库连接断开，尝试第${4 - retryCount}次重试...`)
//       return query(sql, params, retryCount - 1)
//     }
//     throw error
//   }
// }

/**
 * @description 获取所有表信息
 */
router.all("/getTables", async (req, res) => {
  try {
    // 定义SQL语句
    const sqlStr = `select TABLE_SCHEMA AS db, TABLE_NAME AS name, TABLE_COMMENT AS comment from information_schema.TABLES where TABLE_SCHEMA = '${dbConfig.database}'`
    
    const result = await query(sqlStr)
    // console.log(`🚀 ~ result:`, result)
    res.json(responseData({
      data: result
    }))
  } catch (err) {
    console.log(`🚀 ~ err:`, err)
    res.json(responseData({
      type: 'fail',
      message: "获取失败"
    }))
  }
})

/**
 * @description 获取某张表信息
 * @param {
 *          tableName: 表名
 *        }
 */
router.all("/getTableInfo", async (req, res) => {
  // 表集合
  const tableRowSet = req.body.tableRowSet || []
  if (tableRowSet.length === 0) {
    return res.json(responseData({
      type: 'fail',
      message: "至少传入一张表信息"
    }))
  }

  // 表名/字段名转换
  const nameCoverMethod = req.body.nameCoverMethod || 'none'

  try {
    // 所有表信息存储器
    let tableInfoResult = tableRowSet
    
    // 遍历表集合
    for (const i in tableRowSet) {
      const item = tableRowSet[i]
      // 定义SQL语句
      const sqlColumnsStr = `select * from information_schema.COLUMNS where TABLE_SCHEMA = '${dbConfig.database}' AND TABLE_NAME = '${item.name}'`
      
      const result = await query(sqlColumnsStr)
      tableInfoResult[i].columns = result

      // 表名转小驼峰
      tableInfoResult[i].nameSmallHump = _.camelCase(tableInfoResult[i].name)
      // 表名转大驼峰
      tableInfoResult[i].nameLargeHump = _.upperFirst(_.camelCase(tableInfoResult[i].name))

      // 表名/字段名转换方式
      switch (nameCoverMethod) {
        // 小驼峰
        case 'SMALL_HUMP':
          tableInfoResult[i].nameAlias = _.camelCase(tableInfoResult[i].name)
          for (const index in tableInfoResult[i].columns) {
            tableInfoResult[i].columns[index].COLUMN_NAME_ALIAS = _.camelCase(tableInfoResult[i].columns[index].COLUMN_NAME)
          }
          break
        // 大驼峰
        case 'LARGE_HUMP':
          tableInfoResult[i].nameAlias = _.upperFirst(_.camelCase(tableInfoResult[i].name))
          for (const index in tableInfoResult[i].columns) {
            tableInfoResult[i].columns[index].COLUMN_NAME_ALIAS = _.upperFirst(_.camelCase(tableInfoResult[i].columns[index].COLUMN_NAME))
          }
          break
        // 大写+下划线
        case 'UPPERCASE_UNDERLINE':
          tableInfoResult[i].nameAlias = _.camelCase(tableInfoResult[i].name)
          for (const index in tableInfoResult[i].columns) {
            tableInfoResult[i].columns[index].COLUMN_NAME_ALIAS = _.toUpper(_.snakeCase(_.camelCase(tableInfoResult[i].columns[index].COLUMN_NAME)))
          }
          break
        // 不转换
        default:
          tableInfoResult[i].nameAlias = tableInfoResult[i].name
          for (const index in tableInfoResult[i].columns) {
            tableInfoResult[i].columns[index].COLUMN_NAME_ALIAS = tableInfoResult[i].columns[index].COLUMN_NAME
          }
      }
    }
    
    res.json(responseData({
      data: tableInfoResult
    }))
  } catch (err) {
    console.error('获取表信息失败:', err)
    res.json(responseData({
      type: 'fail',
      message: "获取失败"
    }))
  }
})

/**
 * @description 自动生成代码接口
 * @param {
 *          tableName: 表名
 *          columns: [
 *            {
 *              name 字段名称
 *              label 展示文字
 *            }
 *          ]
 *        }
 */
router.all("/genderCode", async (req, res) => {
  if (req.method !== 'POST') {
    return res.json(responseData({
      type: 'fail',
      message: "请使用POST"
    }))
  }

  // 获取表名称
  const tableName = (req.body && req.body.tableName) ? req.body.tableName : ''
  if (tableName === '') {
    return res.json(responseData({
      type: 'fail',
      message: "tableName 为空"
    }))
  }

  // 获取表注释
  const tableComment = (req.body && req.body.tableComment) ? req.body.tableComment : ''
  if (tableComment === '') {
    return res.json(responseData({
      type: 'fail',
      message: "tableComment 为空"
    }))
  }

  // 获取 要生成的代码集
  const codeRowSet = (req.body && req.body.otherConfig.codeRowSet) ? req.body.otherConfig.codeRowSet : []
  if (codeRowSet.length === 0) {
    return res.json(responseData({
      type: 'fail',
      message: "代码集 为空"
    }))
  }

  // 获取 表名/字段名转换
  const nameCoverMethod = (req.body && req.body.nameCoverMethod) ? req.body.nameCoverMethod : ''
  if (nameCoverMethod === '') {
    return res.json(responseData({
      type: 'fail',
      message: "表名/字段名转换 方式 为空"
    }))
  }

  try {
    // 获取表字段信息
    const sqlStr = `select * from information_schema.COLUMNS where TABLE_SCHEMA = '${dbConfig.database}' AND TABLE_NAME = '${tableName}'`
    
    const columnsResult = await query(sqlStr)
    
    let MODULE_VALUE = tableName
    const column = []

    for (const i in columnsResult) {
      const item = columnsResult[i]
      columnsResult[i].COLUMN_NAME_ALIAS = _.camelCase(item.COLUMN_NAME)
      column.push({
        label: item.COLUMN_COMMENT || '',
        prop: item.COLUMN_NAME || ''
      })
    }

    // 小驼峰
    if (nameCoverMethod === 'SMALL_HUMP') {
      // 将表名转为 小驼峰 形式
      MODULE_VALUE = _.camelCase(tableName)
      // 处理字段信息，将字段名称转为：小驼峰
      for (const columnIndex in column) {
        column[columnIndex].prop = _.camelCase(column[columnIndex].prop)
      }
    }

    // 大驼峰
    if (nameCoverMethod === 'LARGE_HUMP') {
      // 将表名转为 大驼峰 形式
      MODULE_VALUE = _.upperFirst(_.camelCase(tableName))
      // 处理字段信息，将字段名称转为：小驼峰
      for (const columnIndex in column) {
        column[columnIndex].prop = _.upperFirst(_.camelCase(column[columnIndex].prop))
      }
    }

    // 大写+下划线
    if (nameCoverMethod === 'UPPERCASE_UNDERLINE') {
      // 将表名转为 大写+下划线 形式
      MODULE_VALUE = _.toUpper(_.snakeCase(_.camelCase(tableName)))
      // 处理字段信息，将字段名称转为： 大写+下划线
      for (const columnIndex in column) {
        column[columnIndex].prop = _.toUpper(_.snakeCase(_.camelCase(column[columnIndex].prop)))
      }
    }
    
    const tableRowSet = []
    tableRowSet.push({
      name: tableName,
      comment: tableComment,
      nameAlias: MODULE_VALUE,
      nameSmallHump: _.camelCase(tableName),
      nameLargeHump: _.upperFirst(_.camelCase(tableName)),
      columns: columnsResult
    })

    const options = {
      // 模块标识
      MODULE_VALUE,
      // 模块名称
      moduleTitle: tableComment,
      // 字段集
      column,
      // 其他配置
      otherConfig: Object.assign({}, req.body.otherConfig, {
        tableRowSet
      })
    }
    
    // 生成代码
    genderCode(options, res)
    
  } catch (err) {
    console.error(`获取表${tableName}信息失败:`, err)
    res.json(responseData({
      type: 'fail',
      message: `获取表${tableName}信息失败`
    }))
  }
})

/**
 * @description 自定义生成代码接口
 * @param {
 *          tableName: 表名
 *          columns: [
 *            {
 *              name 字段名称
 *              label 展示文字
 *            }
 *          ]
 *        }
 */
router.all("/genderCodeCustom", (req, res) => {
  if (req.method !== 'POST') {
    return res.json(responseData({
      type: 'fail',
      message: "请使用POST"
    }))
  }
  const reqBody = req.body
  if (reqBody !== '' && _.isPlainObject(reqBody) && !_.isEmpty(reqBody)) {

    // 生成代码
    genderCode(reqBody, res)

  } else {
    return res.json(responseData({
      type: 'fail',
      message: "入参异常"
    }))
  }
})